using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Media3D;
using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    /// <summary>
    /// This class has all the settings you can edit for fog.
    /// </summary>
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "FogAttributes", Namespace = "SharpGL.SceneGraph")]
    public class FogAttributes : OpenGLAttributes
    {
        #region Private Consts

        private static readonly AttributeMask attributeMask = AttributeMask.Fog;

        #endregion Private Consts

        #region Private Fields

        [DataMember()]
        private bool? enable;
        [DataMember()]
        private FogMode? mode;
        [DataMember()]
        private GLColor? color;
        [DataMember()]
        private float? density;
        [DataMember()]
        private float? start;
        [DataMember()]
        private float? end;

        #endregion Private Fields

        #region Protected Methods

        protected override void OnDeserializing()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Protected Methods

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="FogAttributes"/> class.
        /// </summary>
        public FogAttributes()
        {
            AttributeFlags = attributeMask;
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>
        /// True if any attributes are set
        /// </returns>
        public override bool AreAnyAttributesSet()
        {
            return enable.HasValue ||
                mode.HasValue ||
                color.HasValue ||
                density.HasValue ||
                start.HasValue ||
                end.HasValue;
        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            enable = null;
            mode = null;
            color = null;
            density = null;
            start = null;
            end = null;
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            if (enable.HasValue) gl.EnableIf(OpenGL.GL_FOG, enable.Value);
            if (mode.HasValue) gl.Fog(OpenGL.GL_FOG_MODE, (int)mode.Value);
            if (color.HasValue) gl.Fog(OpenGL.GL_FOG_COLOR, color);
            if (density.HasValue) gl.Fog(OpenGL.GL_FOG_DENSITY, density.Value);
            if (start.HasValue) gl.Fog(OpenGL.GL_FOG_START, start.Value);
            if (end.HasValue) gl.Fog(OpenGL.GL_FOG_END, end.Value);
        }

        #endregion Public Methods

        #region Public Properties

        [Description("Use OpenGL Fog."), Category("Fog")]
        public bool? Enable
        {
            get { return enable; }
            set
            {
                if (enable != value)
                {
                    enable = value;

                    NotifyPropertyChanged("Enable");
                }
            }
        }

        [Description("Fog mode (how the fog density is calculated)."), Category("Fog")]
        public FogMode? Mode
        {
            get { return mode; }
            set
            {
                if (mode != value)
                {
                    mode = value;

                    NotifyPropertyChanged("Mode");
                }
            }
        }

        [Description("Fog color."), Category("Fog")]
        public GLColor? Color
        {
            get { return color; }
            set
            {
                if (color != value)
                {
                    color = value;

                    NotifyPropertyChanged("Color");
                }
            }
        }

        [Description("Fog density (how thick the fog is)."), Category("Fog")]
        public float? Density
        {
            get { return density; }
            set
            {
                if (density != value)
                {
                    density = value;

                    NotifyPropertyChanged("Density");
                }
            }
        }

        [Description("How close to the camera the fog starts."), Category("Fog")]
        public float? Start
        {
            get { return start; }
            set
            {
                if (start != value)
                {
                    start = value;

                    NotifyPropertyChanged("Start");
                }
            }
        }

        [Description("How far away from the camera you get complete fog."), Category("Fog")]
        public float? End
        {
            get { return end; }
            set
            {
                if (end != value)
                {
                    end = value;

                    NotifyPropertyChanged("End");
                }
            }
        }

        #endregion Public Properties
    }
}
